import os
from StringIO import StringIO
from twisted.internet.abstract import FileDescriptor
from twisted.internet.defer import Deferred
from twisted.internet.error import ConnectionDone
from twisted.internet.fdesc import readFromFD, setNonBlocking, _setCloseOnExec

class AsyncFile(FileDescriptor, object):
    def __init__(self, path, reactor=None):
        FileDescriptor.__init__(self, reactor)

        self._fd = os.open(path, os.O_RDONLY)
        setNonBlocking(self._fd)
        _setCloseOnExec(self._fd)
        self.connected = True
        self._writeDisconnected = True
        self.deferred = Deferred()
        self.result = StringIO()

    def _callback(self, data):
        self.result.write(data)

    def connectionLost(self, reason):
        FileDescriptor.connectionLost(self, reason)
        if isinstance(reason.value, ConnectionDone):
            self.result.seek(0)
            self.deferred.callback(self.result.read())
        else:
            self.deferred.errback(reason)

    def read(self):
        self.startReading()
        return self.deferred

    def fileno(self):
        return self._fd

    def doRead(self):
        return readFromFD(self._fd, self._callback)
